package com.iot.toolbox.service;

import org.springframework.stereotype.Service;

import java.util.zip.CRC32;

@Service
public class ChecksumService {

    /**
     * 计算CRC16校验值（Modbus标准）
     */
    public String calculateCRC16(String hex) {
        if (hex == null || hex.isEmpty()) {
            return "";
        }
        
        hex = hex.replaceAll("\\s+", "");
        
        if (hex.length() % 2 != 0) {
            hex = "0" + hex;
        }
        
        byte[] data = hexStringToBytes(hex);
        int crc = 0xFFFF;
        
        for (byte b : data) {
            crc ^= (b & 0xFF);
            for (int i = 0; i < 8; i++) {
                if ((crc & 0x0001) != 0) {
                    crc = (crc >> 1) ^ 0xA001;
                } else {
                    crc >>= 1;
                }
            }
        }
        
        return String.format("%04X", crc);
    }

    /**
     * 计算CRC16校验值（CCITT标准）
     */
    public String calculateCRC16CCITT(String hex) {
        if (hex == null || hex.isEmpty()) {
            return "";
        }
        
        hex = hex.replaceAll("\\s+", "");
        
        if (hex.length() % 2 != 0) {
            hex = "0" + hex;
        }
        
        byte[] data = hexStringToBytes(hex);
        int crc = 0xFFFF;
        
        for (byte b : data) {
            crc ^= (b & 0xFF) << 8;
            for (int i = 0; i < 8; i++) {
                if ((crc & 0x8000) != 0) {
                    crc = (crc << 1) ^ 0x1021;
                } else {
                    crc <<= 1;
                }
            }
        }
        
        return String.format("%04X", crc & 0xFFFF);
    }

    /**
     * 计算CRC32校验值
     */
    public String calculateCRC32(String hex) {
        if (hex == null || hex.isEmpty()) {
            return "";
        }
        
        hex = hex.replaceAll("\\s+", "");
        
        if (hex.length() % 2 != 0) {
            hex = "0" + hex;
        }
        
        byte[] data = hexStringToBytes(hex);
        CRC32 crc32 = new CRC32();
        crc32.update(data);
        
        return String.format("%08X", crc32.getValue());
    }

    /**
     * 计算LRC（纵向冗余校验）
     */
    public String calculateLRC(String hex) {
        if (hex == null || hex.isEmpty()) {
            return "";
        }
        
        hex = hex.replaceAll("\\s+", "");
        
        if (hex.length() % 2 != 0) {
            hex = "0" + hex;
        }
        
        byte[] data = hexStringToBytes(hex);
        byte lrc = 0;
        
        for (byte b : data) {
            lrc ^= b;
        }
        
        return String.format("%02X", lrc & 0xFF);
    }

    /**
     * 计算单字节累加和（8位）
     */
    public String calculateChecksum8(String hex) {
        if (hex == null || hex.isEmpty()) {
            return "";
        }
        
        hex = hex.replaceAll("\\s+", "");
        
        if (hex.length() % 2 != 0) {
            hex = "0" + hex;
        }
        
        byte[] data = hexStringToBytes(hex);
        int sum = 0;
        
        for (byte b : data) {
            sum += (b & 0xFF);
        }
        
        return String.format("%02X", sum & 0xFF);
    }

    /**
     * 计算双字节累加和（16位）
     */
    public String calculateChecksum16(String hex) {
        if (hex == null || hex.isEmpty()) {
            return "";
        }
        
        hex = hex.replaceAll("\\s+", "");
        
        if (hex.length() % 2 != 0) {
            hex = "0" + hex;
        }
        
        byte[] data = hexStringToBytes(hex);
        int sum = 0;
        
        for (byte b : data) {
            sum += (b & 0xFF);
        }
        
        return String.format("%04X", sum & 0xFFFF);
    }

    /**
     * 计算模256校验和（IBC协议）
     */
    public String calculateIBCChecksum(String hex) {
        if (hex == null || hex.isEmpty()) {
            return "";
        }
        
        hex = hex.replaceAll("\\s+", "");
        
        if (hex.length() % 2 != 0) {
            hex = "0" + hex;
        }
        
        byte[] data = hexStringToBytes(hex);
        int sum = 0;
        
        for (byte b : data) {
            sum += (b & 0xFF);
        }
        
        // 模256运算
        sum = sum % 256;
        
        return String.format("%02X", sum);
    }

    /**
     * 计算376.1协议校验和
     */
    public String calculate3761Checksum(String hex) {
        if (hex == null || hex.isEmpty()) {
            return "";
        }
        
        hex = hex.replaceAll("\\s+", "");
        
        if (hex.length() % 2 != 0) {
            hex = "0" + hex;
        }
        
        byte[] data = hexStringToBytes(hex);
        int sum = 0;
        
        for (byte b : data) {
            sum += (b & 0xFF);
        }
        
        // 376.1协议使用模256的校验和
        return String.format("%02X", sum & 0xFF);
    }

    /**
     * 计算Intel HEX格式校验和
     */
    public String calculateIntelHexChecksum(String hex) {
        if (hex == null || hex.isEmpty()) {
            return "";
        }
        
        hex = hex.replaceAll("\\s+", "");
        
        if (hex.length() % 2 != 0) {
            hex = "0" + hex;
        }
        
        byte[] data = hexStringToBytes(hex);
        int sum = 0;
        
        for (byte b : data) {
            sum += (b & 0xFF);
        }
        
        // Intel HEX使用二进制补码
        int checksum = (~sum + 1) & 0xFF;
        
        return String.format("%02X", checksum);
    }

    /**
     * 十六进制字符串转字节数组
     */
    private byte[] hexStringToBytes(String hex) {
        int length = hex.length();
        byte[] data = new byte[length / 2];
        
        for (int i = 0; i < length; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i + 1), 16));
        }
        
        return data;
    }
}
